package list.linked.guard;

/**
 * @author liushiyu@changingedu.com
 * @desc 守卫节点
 * @date 9/7/2019 下午2:44
 */
public class LinkedList<T> {

    private Node<T> head;
    private int size;

    public LinkedList() {
        this.head = new Node(null);
        this.size = 0;
    }

    public void add(T data){
        Node newNode = new Node(data);
        Node lastNode = head;
        while (lastNode.next != null){
            lastNode = lastNode.next;
        }
        lastNode.next = newNode;
        size++;
        return;
    }

    public T get(int index){
        checkElementIndex(index);
        Node<T> getNode = head.next;
        for (int i = 0; i < index; i++) {
            getNode = getNode.next;
        }
        return getNode.data;
    }

    public T remove(int index){
        checkElementIndex(index);
        Node<T> preNode = head;
        for (int i = 0; i < index; i++) {
            preNode = preNode.next;
        }
        Node<T> removeNode = preNode.next;
        preNode.next = removeNode.next;
        size--;
        return removeNode.data;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0 || head == null;
    }

    public boolean isNotEmpty() {
        return !isEmpty();
    }

    private boolean isElementIndex(int index) {
        if (index < 0 || index >= size) {
            return false;
        }
        return true;
    }

    private void checkElementIndex(int index) {
        if (!isElementIndex(index)) {
            throw new IndexOutOfBoundsException();
        }
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("LinkedList{");
        Node node = head;
        for (int i = 0; i < size - 1; i++) {
            node = node.next;
            sb.append(i);
            sb.append(":");
            sb.append(node.data.toString());
            sb.append(",");
        }
        node = node.next;
        sb.append(size - 1);
        sb.append(":");
        sb.append(node.data.toString());
        sb.append("}");
        return sb.toString();
    }

    class Node<T> {
        private T data;
        private Node<T> next;

        public Node(T data) {
            this.data = data;
            this.next = null;
        }
    }
}
